/* @author Michael Antemann
 *  @created on 29.10.2008 
 *  Steuert das Spiel
 *  updated on 18.11.08 totally worked over
 *  Alles auf englisch umbenannt! die 
 *  fassaden klasse an das neue array vom gui angepasst
 *  steine nehmen angepasst, das keine eigenen genommen werden 
 *  06.12.2008 . 
 *  	Move methoden die was tun in rules ausgelagert.
 *  	move() überlagert mit move(int)
 *  	move(int) prüft regeln und gibt gewählte mulde an Rules.makemove weiter am laufen,
 *   
 *   für ki beteiligung 
 *  	move() -:> ermittelt int wert über die ki move methode und gibt diesen dann an die norme move(int)
 *  	der ki zug wird normal behandelt wie der vom spieler auch
 *   
 *   Änderungen 09.12.2008 Michael Antemann:
 *   run() Methode entfernt
 *   nicht benutzte variablen werte variabeln imports entfernt
 *  
 *  Schleife für move hinzugefügt. keine rekursion mehr!
 *  parameter von ki.move(int[], int[] ,int ) korrigiert. bekam falsches feeld für B beachte problem eintrag bei todo
 *  
 *  wenn eine ki das spiel beginnt lös startGame dies am schluss aus.
 */

package de.fhhannover.inform.wari.grp8.spiel;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Observable;

import de.fhhannover.inform.studienklassen.semester3.GeneralStatics;
import de.fhhannover.inform.wari.grp8.gui.Logger;
import de.fhhannover.inform.wari.strategy.MoveStrategy;

public class GameFlow extends Observable {
	boolean logging= true;
	Logger logwriter = new Logger("");
	Board mBoard = new Board(0);
	private MoveStrategy mKiA;
	private MoveStrategy mKiB;

	private Rules ruler;
	int thinktimeInMilliseconds = 10000;

	private String mStrategyNameA = "TheSimpliest";
	private String mStrategyNameB = "TheSimpliest";

	String spielerName_log;
	int muldenid_log;
	int muldenanzahl_log;
	boolean whois_log;
	int gewinnmuldenanzahl_log;

	public GameFlow() {
		super();
		mBoard = new Board(0);
	}

	public void startGame(String nA, String nB, boolean tA, boolean tB,
			boolean starter) {
		mBoard.initialisation(4, starter, tA, tB, nA, nB);
		/*
		 * // guter test für zwangszug int[] a= {0,0,0,1,2,1}; int[] b=
		 * {1,0,0,0,0,0}; mBoard.setPitsA(a); mBoard.setPitsB(b);
		 */
		
		/*  //Test unentschieden 
		int[] a= {1,0,0,0,0,1}; int[] b= {1,0,0,0,0,1};
		  mBoard.setPitsA(a); mBoard.setPitsB(b);
		 */
		/*
		 * //Test int[] a= {0,0,0,0,0,0}; int[] b= {1,0,0,0,1,0};
		 * mBoard.setPitsA(a); mBoard.setPitsB(b);
		 */
		
		ruler = new Rules(mBoard,this);
		mBoard.setStillrunning(true);
		if (mBoard.getTypeA() || mBoard.getTypeB()) {
			try {
				kiMode();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// move(); //move fuer ki
		}
		// System.out.println(mBoard.toFString());
		shouldUpdate("Das Spiel kann Begonnen werden!");
		
		if (mBoard.getType(mBoard.getWhoseTurn())) {
			move(-1);
		}
	}

	public void endgame() {
		System.out.println("Das Spiel wird Beendet");
		// Test, der gui wird geschlossen, das brett und der fluss existieren
		// aber ncoh
		// aufräum arbeiten log // maybe log in datei sichern usw // ki killen
		/*
		 * try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); }
		 */
		System.out.println(mBoard.toString());
		System.exit(0);
	}

	private void kiMode() throws SecurityException, ClassNotFoundException,
			NoSuchMethodException {
		if (mBoard.getTypeA()) {
			mKiA = (MoveStrategy) StrategyHandler.getStrategyHandler()
					.getStrategyByName(mStrategyNameA);
		}
		if (mBoard.getTypeB()) {
			mKiB = (MoveStrategy) StrategyHandler.getStrategyHandler()
					.getStrategyByName(mStrategyNameB);
		}
	}

	private void error(String s) {
		System.out.println("Fehler Fehler Fehler:\n" + s);
logwriter.close();
		System.exit(0);
	}

	// controller methode für menschen und ki!

	public int move(int in) {
		while (mBoard.isStillrunning()) {
			if (mBoard.getWhoseTurn() && mBoard.getTypeA()) {
				in = kiMove(true);
			} else if (!mBoard.getWhoseTurn() && mBoard.getTypeB()) {
				in = kiMove(false);
			}

			muldenid_log = in;
			whois_log = mBoard.getWhoseTurn();
			if (whois_log) {
				spielerName_log = mBoard.getNameA();
				muldenanzahl_log = mBoard.getPitA(muldenid_log);
			} else {
				spielerName_log = mBoard.getNameB();
				muldenid_log = muldenid_log - 6;
				muldenanzahl_log = mBoard.getPitB(muldenid_log);
			}
			if (ruler.preCheck(in)) {
				int success = ruler.makeMove(in);
				if (success == -1) {
					this.error("Beim ausführen des Zuges trat ein Fehler auf");
				}
				ruler.postCheck();
				// System.out.println(mBoard.toFString());
				mBoard.nextPlayer();
				shouldUpdate("An der Reihe:" + mBoard.getName(mBoard.getWhoseTurn()));
				
			} else {
				shouldUpdate("Dieser Zug ist nicht erlaubt!");
			}
		
				if(logging){
				
				logwriter.writeIntoFile(this.toString()); // schreibe in die
				// // Logdatei
				
				  
				  logwriter.writeIntoFile(mBoard.toFString());
				 
				 }
			
			if (whois_log) {
				gewinnmuldenanzahl_log = mBoard.getWinPitA();
			} else {
				gewinnmuldenanzahl_log = mBoard.getWinPitB();
			}
			if (!mBoard.isStillrunning()) {
				shouldUpdate("Spiel zu Ende: Sieger: "
						+ ruler.siegerString());
			}
			if (!mBoard.getType(mBoard.getWhoseTurn())) {
				return 0;
			}
		}
		return 1;
	}

	// die Ki eine mulde wählen lassen
	private int kiMove(boolean b) {
		int choice = -1;
		if (b) {
			choice = mKiA.move(mBoard.getPitsA(), mBoard.getPitsB(),
					thinktimeInMilliseconds);
			if (choice < 6 && choice > -1) {

			} else {
				error("Ki übergibt falschen int wert");
			}
		} else {
			choice = (mKiB.move(mBoard.getPitsB(), mBoard.getPitsA(),
					thinktimeInMilliseconds));
			choice = choice + 6;
			if (!(choice > 5) && !(choice < 12)) {
				error("Ki übergibt falschen int wert");
			}
		}
		return choice;
	}

	/*
	 * updated by Shanmugaesan on 05.12.08 setStragyname wurde hinzuf�gt
	 */
	public void setStrategyNameA(String nameA) {
		this.mStrategyNameA = nameA;
	}

	public void setStrategyNameB(String nameB) {
		this.mStrategyNameA = nameB;
	}

	/* **************************** */

	// Controller Methoden
	public void setNameA(String s) {
		mBoard.setNameA(s);
	}

	public void setNameB(String s) {
		mBoard.setNameB(s);
	}

	public void setName(String a, String b) {
		mBoard.setNameA(a);
		mBoard.setNameB(b);
	}

	public void setTypeA(boolean in) {
		// false Mensch , true KI
		mBoard.setTypeA(in);
	}

	public void setTypeB(boolean in) {
		// false Mensch , true KI
		mBoard.setTypeB(in);
	}

	public void setWhoseTurn(boolean b) {
		mBoard.setWhoseTurn(b);
	}

	public boolean getTypeA() {
		return mBoard.getTypeA();
	}

	public boolean getTypeB() {
		return mBoard.getTypeB();
	}

	public int[] getBoardPits() {
		int[] arr1 = mBoard.getPitsA();
		int[] arr2 = mBoard.getPitsB();
		int[] arr = GeneralStatics.connectArray(arr1, arr2);
		return arr;
	}

	public int getWinPitA() {
		// TODO Auto-generated method stub
		return mBoard.getWinPitA();
	}

	public int getWinPitB() {
		// TODO Auto-generated method stub
		return mBoard.getWinPitB();
	}

	public String getNameA() {
		return mBoard.getNameA();
	}

	public String getNameB() {
		return mBoard.getNameB();
	}

	public Board getBoard() {
		return this.mBoard;
	}

	public boolean getWhoesTurn() {
		return mBoard.getWhoseTurn();
	}

	public int[] getPitsA() {
		return mBoard.getPitsA();
	}

	public int[] getPitsB() {
		return mBoard.getPitsB();
	}

	public boolean isRunning() {
		return mBoard.isStillrunning();
	}

	public void setUpdate(boolean b) {
		mBoard.setUpdate(b);
	}
	public boolean getUpdate(){
		return mBoard.getUpdate();
	}
	@SuppressWarnings("unused")
	private void setBoard(Board brett) {
		mBoard = brett;
		// mBoard.reset(4);
	}

	public String toString() {
		Date datum = new Date();
		SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss dd-MM-yy");
		muldenid_log += 1; // wegen ArrayIndex
		return df.format(datum) + " =>" + " ZugNr : "
				+ (mBoard.getTurnCount() - 1) + " " + spielerName_log + " zog "
				+ muldenid_log + ".Mulde mit " + muldenanzahl_log
				+ " Steinen. " + "Gewinnmuldestatus : "
				+ gewinnmuldenanzahl_log;
	}
	 void shouldUpdate(String s) {
		super.setChanged();
		super.notifyObservers("ZugNr: " + mBoard.getTurnCount() + " " + s);
	
	}
}
